package timing.ukulele.web.config;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.NonNull;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import timing.ukulele.common.constant.RequestConstant;
import timing.ukulele.web.model.OperatorInfo;
import timing.ukulele.web.util.RequestUtil;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;

/**
 * Web 配置
 */
@Slf4j
@Configuration
@ConditionalOnProperty(name = "ukulele.web.operator-interceptor", havingValue = "true")
public class WebOperatorInterceptorConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new HandlerInterceptor() {
            @Override
            public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws Exception {
                // 配置操作人信息
                OperatorInfo authInfo = getAuthInfo(request);
                RequestUtil.setOperator(authInfo);
                return HandlerInterceptor.super.preHandle(request, response, handler);
            }

            @Override
            public void postHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler, ModelAndView modelAndView) throws Exception {
                HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
            }

            @Override
            public void afterCompletion(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler, Exception ex) throws Exception {
                // 清除操作人信息
                RequestUtil.resetOperator();
                HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
            }
        });
    }

    /**
     * 从 Request Header 中获取权限信息
     *
     * @param request {@link HttpServletRequest}
     * @return {@link OperatorInfo}
     */
    private OperatorInfo getAuthInfo(HttpServletRequest request) {
        String tenantIdStr = RequestUtil.getRequestHeader(request, RequestConstant.Header.X_AUTH_TENANT);
        long tenantId = 0;
        if (ObjectUtil.isNotNull(tenantIdStr) && StrUtil.isNumeric(tenantIdStr)) {
            tenantId = Long.parseLong(tenantIdStr);
        }
        String bizTenantIdStr = RequestUtil.getRequestHeader(request, RequestConstant.Header.X_AUTH_BIZ_TENANT);
        long bizTenantId = 0;
        if (ObjectUtil.isNotNull(bizTenantIdStr) && StrUtil.isNumeric(bizTenantIdStr)) {
            bizTenantId = Long.parseLong(bizTenantIdStr);
        }
        String username = RequestUtil.getRequestHeader(request, RequestConstant.Header.X_AUTH_USER);
        String userIdStr = RequestUtil.getRequestHeader(request, RequestConstant.Header.X_AUTH_USER_ID);
        long userId = -1;
        if (ObjectUtil.isNotNull(userIdStr) && StrUtil.isNumeric(userIdStr)) {
            userId = Long.parseLong(userIdStr);
        }
        String name = RequestUtil.getRequestHeader(request, RequestConstant.Header.X_AUTH_USER_NAME);
        if(name != null) {
            try {
                name = URLDecoder.decode(name, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        String nickname = RequestUtil.getRequestHeader(request, RequestConstant.Header.X_AUTH_USER_NICKNAME);
        int terminal = -1;
        String terminalStr = RequestUtil.getRequestHeader(request, RequestConstant.Header.X_AUTH_USER_TERMINAL);
        if (ObjectUtil.isNotNull(terminalStr) && StrUtil.isNumeric(terminalStr)) {
            terminal = Integer.parseInt(terminalStr);
        }
        return new OperatorInfo(tenantId, bizTenantId, username, userId, name, nickname, terminal);
    }
}
